#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
#endregion

namespace pxt
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        NetworkSession networkSession;

        ContentManager content;
        SpriteFont gameFont;

        Vector2 playerPosition = new Vector2(100, 100);
        Vector2 enemyPosition = new Vector2(100, 100);

        Random random = new Random();

        float pauseAlpha;
        bool mRoundOver = false;


        Level test_level;
        //Player player1;
        //Player player2;
        List<Team> mTeams;
        public CGameScreen mScreen;

        // Internal State
        protected enum ScreenStates { LOADING = 1, GAMEPLAY, GAME_OVER, PAUSE };
        protected ScreenStates mCurState;

        #endregion

        #region Properties


        /// <summary>
        /// The logic for deciding whether the game is paused depends on whether
        /// this is a networked or single player game. If we are in a network session,
        /// we should go on updating the game even when the user tabs away from us or
        /// brings up the pause menu, because even though the local player is not
        /// responding to input, other remote players may not be paused. In single
        /// player modes, however, we want everything to pause if the game loses focus.
        /// </summary>
        new bool IsActive
        {
            get
            {
                if (networkSession == null)
                {
                    // Pause behavior for single player games.
                    return base.IsActive;
                }
                else
                {
                    // Pause behavior for networked games.
                    return !IsExiting;
                }
            }
        }


        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen(NetworkSession networkSession)
        {
            this.networkSession = networkSession;

            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            test_level = new Level();
            test_level.CreateTestLevel();


            // there will always be 4 players - they just wont be in game
            Player player1 = new Player();
            Player player2 = new Player();
            Player player3 = new Player();
            Player player4 = new Player();

            GameSystems.CollisionSystem.Players.Add(player1);
            GameSystems.CollisionSystem.Players.Add(player2);
            GameSystems.CollisionSystem.Players.Add(player3);
            GameSystems.CollisionSystem.Players.Add(player4);

            mScreen = new CGameScreen();
            mScreen.AddElement(new CScreenImageUnitFrame(new Vector2( 25.0f, 10.0f), player1.Wizard));
            mScreen.AddElement(new CScreenImageUnitFrame(new Vector2(320.0f, 10.0f), player2.Wizard));
            mScreen.AddElement(new CScreenImageUnitFrame(new Vector2(704.0f, 10.0f), player3.Wizard));
            mScreen.AddElement(new CScreenImageUnitFrame(new Vector2(999.0f,10.0f), player4.Wizard));

            // set up the teams!
            Team tmpTeam1 = new Team(1);
            tmpTeam1.AddPlayer(player1);
            tmpTeam1.AddPlayer(player2);

            Team tmpTeam2 = new Team(2);
            tmpTeam2.AddPlayer(player3);
            tmpTeam2.AddPlayer(player4);

            test_level.AddTeam(tmpTeam1);
            test_level.AddTeam(tmpTeam2);

            //test_level.CreateAnnouncements();
            // this will obviously be moved!
            test_level.StartRound();

            mCurState = ScreenStates.GAMEPLAY;
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameFont = content.Load<SpriteFont>("gamefont");

            // A real game would probably have more content than this sample, so
            // it would take longer to load. We simulate that by delaying for a
            // while, giving you a chance to admire the beautiful loading screen.
            Thread.Sleep(1000);


            test_level.Load();
            //player1.Load(content);
            //player2.Load(content);

            foreach (Player p in GameSystems.CollisionSystem.Players)
            {
                p.Load();
            }


            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            foreach (Team team in test_level.Teams)
            {
                if (team.AllMembersDead && !mRoundOver)
                {
                    GameSystems.AnnouncementSystem.FireAnnouncement("TEAM 1 WINS!!!", Color.Red);
                    mRoundOver = true;
                    mCurState = ScreenStates.GAME_OVER;
                }
            }

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                switch (mCurState)
                {
                    case ScreenStates.GAMEPLAY:
                        // todo - game update code
                        test_level.Update(gameTime);

                        // player1.Update(gameTime);
                        // player2.Update(gameTime);

                        foreach (Player p in GameSystems.CollisionSystem.Players)
                        {
                            p.Update(gameTime);
                        }
                        GameSystems.CollisionSystem.Update(gameTime);
                        mScreen.Update(gameTime);
                        break;
                    case ScreenStates.GAME_OVER:
                        //ExitScreen();
                        break;
                    default:
                        break;
                }
            }

            // If we are in a network game, check if we should return to the lobby.
            if ((networkSession != null) && !IsExiting)
            {
                if (networkSession.SessionState == NetworkSessionState.Lobby)
                {
                   // LoadingScreen.Load(ScreenManager, true, null,
                    //                   new BackgroundScreen(),
                    //                   new LobbyScreen(networkSession));
                }
            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            //Console.WriteLine("Num Players:" + mPlayers.Count);

            switch (mCurState)
            {
                case ScreenStates.GAMEPLAY:
                    // for now just use our system
                    for (int i = 0; i < GameSystems.CollisionSystem.Players.Count; i++)
                    {
                        //GameSystems.CollisionSystem.Players[i].HandleInput(input, i);
                        this.HandlePlayerInput(input, (PlayerIndex)i);
                    }
                    break;
                case ScreenStates.GAME_OVER:
                    break;
                default:
                    break;
            }
        }


        /// <summary>
        /// Handles input for the specified player. In local game modes, this is called
        /// just once for the controlling player. In network modes, it can be called
        /// more than once if there are multiple profiles playing on the local machine.
        /// Returns true if we should continue to handle input for subsequent players,
        /// or false if this player has paused the game.
        /// </summary>
        bool HandlePlayerInput(InputState input, PlayerIndex playerIndex)
        {
            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !(input.CurrentGamePadStates[(int)playerIndex].IsConnected) &&
                                       input.GamePadWasConnected[(int)playerIndex];

            if (input.IsPauseGame(playerIndex) || gamePadDisconnected)
            {
                //ScreenManager.AddScreen(new PauseMenuScreen(networkSession), playerIndex);
                return false;
            }

            GameSystems.CollisionSystem.Players[(int)playerIndex].HandleInput(input, (int)playerIndex);

            return true;
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            //SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            //spriteBatch.Begin();

            test_level.Draw();
            //player1.Draw(spriteBatch);
            //player2.Draw(spriteBatch);

            foreach (Player p in GameSystems.CollisionSystem.Players)
            {
                p.Draw();
            }

            GameSystems.CollisionSystem.Draw();
            mScreen.Draw();

            if (networkSession != null)
            {
                string message = "Players: " + networkSession.AllGamers.Count;
                Vector2 messagePosition = new Vector2(100, 480);
                //spriteBatch.DrawString(gameFont, message, messagePosition, Color.White);
                GameSystems.Graphics.DrawText(message, messagePosition, Color.White);
            }

            //spriteBatch.End();


        }


        #endregion
    }
}
